//
// Created by 69566 on 25-8-20.
//

#include "drv_key.h"

#include <stddef.h>

#include "stm32f4xx_hal.h"

#define KEY_CHECK_TIME 20
#define KEY_SHORT_TIME 100
#define KEY_LONG_TIME 500
#define KEY_MAX_NUM 5
/*************时间获取函数********** */
static uint8_t    key_num = 0;
static key_info_t key_info[KEY_MAX_NUM];
uint32_t          GetTick(void)
{
    return HAL_GetTick();
}
/******************************** */
key_info_t* key_init(gpio_read_fn callback, uint8_t valid_leavel)
{
    if (key_num >= KEY_MAX_NUM)
        return NULL;
    key_info_t* key   = &key_info[key_num++];
    key->gpio_read    = callback;
    key->valid_leavel = valid_leavel;
    key->status       = KEY_IDEL;
    return key;
}
void key_event_register(key_info_t* key, key_event_e event, key_event_callback callback)
{
    if (NULL == key || NULL == callback)
    {
        printf("key event register error\n");
        return;
    }
    key->event_callback[event] = callback;
}
void _key_handle(key_info_t* key)
{
    if (NULL == key)
    {
        printf("key handle error\n");
        return;
    }
    key->current_leavel = key->gpio_read();
    key->current_time   = GetTick();
    switch (key->status)
    {
        case KEY_IDEL:
            if (key->current_leavel == key->valid_leavel)
            {
                key->last_time = GetTick();
                key->status    = KEY_CHECK;
            }
            break;
        case KEY_CHECK:
            if (key->current_time - key->last_time > KEY_CHECK_TIME &&
                key->current_leavel == key->valid_leavel)
            {
                key->status = KEY_PRESS;
            }
            else if (key->current_leavel != key->valid_leavel)
            {
                key->status = KEY_IDEL;
            }
            break;
        case KEY_PRESS:
            if (key->event_callback[PRESS_EVENT] != NULL)
            {
                key->event_callback[PRESS_EVENT]();
            }
            key->last_time = GetTick();
            key->status    = KEY_SHORT_PRESS;
            break;
        case KEY_SHORT_PRESS:
            if (key->current_time - key->last_time > KEY_SHORT_TIME &&
                key->current_leavel == key->valid_leavel)
            {
                key->status = KEY_LONG_PRESS;
            }
            else if (key->current_leavel != key->valid_leavel)
            {
                key->status = KEY_IDEL;
                if (key->event_callback[SHORT_PRESS_EVENT] != NULL)
                {
                    key->event_callback[SHORT_PRESS_EVENT]();
                }
            }
            break;
        case KEY_LONG_PRESS:
            if (key->current_time - key->last_time > KEY_LONG_TIME &&
                key->current_leavel == key->valid_leavel)
            {
                key->last_time = GetTick();
                if (key->event_callback[LONG_PRESS_EVENT] != NULL)
                {
                    key->event_callback[LONG_PRESS_EVENT]();
                }
            }
            else if (key->current_leavel != key->valid_leavel)
            {
                if (key->event_callback[RELEASE_EVENT] != NULL)
                {
                    key->event_callback[RELEASE_EVENT]();
                }
                key->status = KEY_IDEL;
            }
            break;
        default:
            break;
    }
}
void drv_key_handle(void)
{

    for (int i = 0; i < key_num; i++)
    {
        _key_handle(&key_info[i]);
    }
}